package tables

import (
	"fmt"
	"server/application/db/schema/dbops"
	"server/application/db/schema/sdto"
	"server/application/db/schema/sentity"

	"server/application/dto"
	"server/pkg/myexcel"
	"server/pkg/where"
	"time"

	"gorm.io/gorm"
)

type DbSvcTrip struct {
	dbWrite *gorm.DB
	dbRead  *gorm.DB
}

func NewTrip(dbWrite_, dbRead_ *gorm.DB) *DbSvcTrip {
	return &DbSvcTrip{
		dbWrite: dbWrite_,
		dbRead:  dbRead_,
	}
}

// Create 创建数据
func (s *DbSvcTrip) Create(dtoCreate *sentity.Trip) (*sentity.Trip, error) {

	if dtoCreate.ID == 0 { //新增
		err := dbops.CreateNew(dtoCreate, s.dbWrite)
		if dtoCreate == nil || dtoCreate.ID <= 0 {
			return nil, fmt.Errorf("创建失败，info数据为空")
		}
		return dtoCreate, err
	} else { //修改
		err := dbops.UpdateNew(&dbops.UpdateConfNew{
			Wheres:     where.FormatOne("id", "=", dtoCreate.ID),
			NewEntity:  new(sentity.Trip),
			Db:         s.dbWrite,
			DataUpdate: dtoCreate,
		})
		if err != nil {
			return nil, err
		}
		return dtoCreate, nil
	}
}

// FindOne 查询一条数据
func (s *DbSvcTrip) FindOne(wheres []*where.Condition) (*sentity.Trip, error) {
	entityInfo := new(sentity.Trip)
	err := dbops.FindOneNew(&dbops.FindOneConfig{
		Wheres:    wheres,
		Db:        s.dbRead,
		NewEntity: entityInfo,
	})
	if err != nil {
		return nil, err
	}
	if entityInfo == nil || entityInfo.ID <= 0 {
		return nil, fmt.Errorf("查询到的数据为空")
	}

	return entityInfo, nil
}

// FindList 查询列表数据
func (s *DbSvcTrip) FindList(wheres []*where.Condition, extra *where.Extra) ([]*sentity.Trip, uint, error) {

	var entityList []*sentity.Trip
	//传入的entityList必须要加 &取地址符号，切片本身并不是指针，向函数传递一个切片时，实际上是复制了该切片的结构体
	err := dbops.FindListNew(&dbops.FindListConfig{
		Conditions:     wheres,
		Db:             s.dbRead,
		Extra:          extra,
		NewEntityList:  &entityList,
		GetSoftDelData: false,
		// Fields:        []string{"ID"},
		// RelationList: []*dbops.RelationItem{},
	})
	if err != nil {
		return nil, 0, err //返回空切片，0，错误
	}

	//开始统计总数
	total, err := dbops.GetTotalWithDb(wheres, new(sentity.Trip), s.dbRead)
	if err != nil {
		return []*sentity.Trip{}, 0, err
	}

	return entityList, uint(total), nil
}

// Update 更新数据
func (s *DbSvcTrip) Update(wheres []*where.Condition, dtoUpdate *sentity.Trip, columnsCfg ...string) error {
	// dbops.UpdateWithDb(wheres, new(sentity.Trip), dtoUpdate, s.dbWrite, columnsCfg...)
	err := dbops.UpdateNew(&dbops.UpdateConfNew{
		Wheres:           wheres,
		NewEntity:        new(sentity.Trip),
		Db:               s.dbWrite,
		UpdateColumnsCfg: columnsCfg,
		DataUpdate:       dtoUpdate,
	})
	return err
}

// Delete 删除数据
func (s *DbSvcTrip) Delete(wheres []*where.Condition) error {
	err := dbops.DeleteNew(&dbops.DeleteConfig{
		Wheres:     wheres,
		Db:         s.dbWrite,
		SoftDelete: false,
		NewEntity:  new(sentity.Trip),
	})
	return err
}

// GetTotal 获取总数
func (s *DbSvcTrip) GetTotal(wheres []*where.Condition) (int64, error) {
	total, err := dbops.GetTotalWithDb(wheres, new(sentity.Trip), s.dbRead)
	return total, err
}

// ImportData 导入excel文件
func (s *DbSvcTrip) ImportData(filePath string, WhenErrorUpdate bool) (err error) {
	defer func() { //捕获异常
		if p := recover(); p != nil {
			err = fmt.Errorf("panic occurred: %v", p)
		}
	}()
	var data []sdto.TripCreate
	result, err := myexcel.ParseExcel(filePath, &sdto.TripCreate{})
	if err != nil {
		return err
	}
	//转成切片
	for _, item := range result {
		data = append(data, *item.(*sdto.TripCreate))
	}

	//插入数据
	err = dbops.CreateBatch(data, new(sentity.Trip), WhenErrorUpdate, s.dbWrite)
	if err != nil {
		return err
	}

	return err
}

// ExportData  导出数据
func (s *DbSvcTrip) ExportData(params *dto.ReqSearch) (string, error) {
	total, err := s.GetTotal(params.Wheres)
	if err != nil {
		return "", err
	}
	if total > int64(params.Extra.PageSize) {
		return "", fmt.Errorf("导出总数%v大于%v,请分批导出", total, params.Extra.PageSize)
	}
	//开始构造数据并存入本地文件
	list, _, _ := s.FindList(params.Wheres, params.Extra)
	if list == nil || len(list) <= 0 {
		return "", fmt.Errorf("导出数据为空")
	}
	//开始写入数据
	filePath := "uploads/export/exportTrip_" + time.Now().Format("20060102150105") + ".xlsx"
	err = myexcel.GenStructListFile(list, &sdto.TripInfo{}, filePath)
	if err != nil {
		return "", err
	}
	return filePath, nil
}
